package com.jinwei.qunguanjia.web.system.controller;

import com.jinwei.qunguanjia.common.annotation.Log;
import com.jinwei.qunguanjia.common.constant.UserConstants;
import com.jinwei.qunguanjia.common.core.domain.Response;
import com.jinwei.qunguanjia.common.core.page.PageDataInfo;
import com.jinwei.qunguanjia.common.enums.BusinessTypeEnum;
import com.jinwei.qunguanjia.common.utils.*;
import com.jinwei.qunguanjia.common.utils.poi.ExcelUtil;
import com.jinwei.qunguanjia.system.dto.SysLoginUser;
import com.jinwei.qunguanjia.system.service.TokenService;
import com.jinwei.qunguanjia.system.dto.SysRoleDTO;
import com.jinwei.qunguanjia.system.dto.SysUserDTO;
import com.jinwei.qunguanjia.system.service.SysPermissionService;
import com.jinwei.qunguanjia.system.service.SysRoleService;
import com.jinwei.qunguanjia.system.service.SysUserService;
import com.jinwei.qunguanjia.system.utils.SecurityUtils;
import com.jinwei.qunguanjia.web.system.vo.SysRoleVO;
import com.jinwei.qunguanjia.web.system.vo.SysUserVO;
import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Objects;

/**
 * 角色信息
 *
 * @author yuanzs
 */
@RestController
@RequestMapping("/system/role")
@Validated
public class SysRoleController {

    @Resource
    private SysRoleService sysRoleService;

    @Resource
    private TokenService tokenService;

    @Resource
    private SysPermissionService sysPermissionService;

    @Resource
    private SysUserService sysUserService;

    /**
     * 新增角色
     * @param sysRoleVO 对象
     */
    @PreAuthorize("@ss.hasPermission('system:role:save')")
    @Log(title = "角色管理-新增", businessType = BusinessTypeEnum.INSERT)
    @PostMapping("/save")
    public Response save(@Validated @RequestBody SysRoleVO sysRoleVO) throws IllegalAccessException {
        SysRoleDTO sysRoleDTO = new SysRoleDTO();
        BeanUtils.copyProperties(sysRoleVO, sysRoleDTO);
        if (UserConstants.NOT_UNIQUE.equals(sysRoleService.checkRoleNameUnique(sysRoleDTO))) {
            return Response.fail("新增角色'" + sysRoleVO.getRoleName() + "'失败，角色名称已存在");
        } else if (UserConstants.NOT_UNIQUE.equals(sysRoleService.checkRoleKeyUnique(sysRoleDTO))) {
            return Response.fail("新增角色'" + sysRoleVO.getRoleName() + "'失败，角色权限已存在");
        }
        sysRoleService.save(sysRoleDTO);
        return Response.success();
    }

    /**
     * 修改角色
     * @param sysRoleVO 对象
     */
    @PreAuthorize("@ss.hasPermission('system:role:update')")
    @Log(title = "角色管理-修改角色", businessType = BusinessTypeEnum.UPDATE)
    @PutMapping("/update")
    public Response update(@Validated @RequestBody SysRoleVO sysRoleVO) throws IllegalAccessException {
        sysRoleService.checkRoleAllowed(sysRoleVO.getRoleId());
        sysRoleService.checkRoleDataScope(sysRoleVO.getRoleId());
        SysRoleDTO sysRoleDTO = new SysRoleDTO();
        BeanUtils.copyProperties(sysRoleVO, sysRoleDTO);
        if (UserConstants.NOT_UNIQUE.equals(sysRoleService.checkRoleNameUnique(sysRoleDTO))) {
            return Response.fail("修改角色'" + sysRoleVO.getRoleName() + "'失败，角色名称已存在");
        } else if (UserConstants.NOT_UNIQUE.equals(sysRoleService.checkRoleKeyUnique(sysRoleDTO))) {
            return Response.fail("修改角色'" + sysRoleVO.getRoleName() + "'失败，角色权限已存在");
        }
        if (sysRoleService.update(sysRoleDTO) > 0) {
            // 更新缓存用户权限
            SysLoginUser loginUser = SecurityUtils.getLoginUser();
            if (!SecurityUtils.isAdmin()) {
                Objects.requireNonNull(loginUser).setPermissions(sysPermissionService.listMenuPermission(loginUser.getUserId()));
                loginUser.setUserJson(JsonUtils.toJsonString(sysUserService.getUserByUserName(loginUser.getUsername())));
                tokenService.setLoginUser(loginUser);
            }
        }
        return Response.success();
    }

    /**
     * 修改数据权限
     * @param sysRoleVO 对象
     */
    @PreAuthorize("@ss.hasPermission('system:role:update')")
    @Log(title = "角色管理-修改数据权限", businessType = BusinessTypeEnum.UPDATE)
    @PutMapping("/dataScope")
    public Response dataScope(@RequestBody SysRoleVO sysRoleVO) {
        sysRoleService.checkRoleAllowed(sysRoleVO.getRoleId());
        sysRoleService.checkRoleDataScope(sysRoleVO.getRoleId());
        SysRoleDTO sysRoleDTO = new SysRoleDTO();
        BeanUtils.copyProperties(sysRoleVO, sysRoleDTO);
        sysRoleService.updateDataScope(sysRoleDTO);
        return Response.success();
    }

    /**
     * 修改状态
     * @param sysRoleVO 对象
     */
    @PreAuthorize("@ss.hasPermission('system:role:update')")
    @Log(title = "角色管理-修改状态", businessType = BusinessTypeEnum.UPDATE)
    @PutMapping("/changeStatus")
    public Response changeStatus(@RequestBody SysRoleVO sysRoleVO) {
        sysRoleService.checkRoleAllowed(sysRoleVO.getRoleId());
        sysRoleService.checkRoleDataScope(sysRoleVO.getRoleId());
        SysRoleDTO sysRoleDTO = new SysRoleDTO();
        BeanUtils.copyProperties(sysRoleVO, sysRoleDTO);
        sysRoleService.updateRoleStatus(sysRoleDTO);
        return Response.success();
    }

    /**
     * 删除角色
     * @param ids 角色id列表
     */
    @PreAuthorize("@ss.hasPermission('system:role:remove')")
    @Log(title = "角色管理-删除角色", businessType = BusinessTypeEnum.DELETE)
    @DeleteMapping("/{ids}")
    public Response remove(@PathVariable List<String> ids) {
        sysRoleService.remove(ids);
        return Response.success();
    }

    /**
     * 获取角色列表
     * @param sysRoleVO 对象
     */
    @PreAuthorize("@ss.hasPermission('system:role:list')")
    @GetMapping("/list")
    public PageDataInfo<SysRoleVO> list(SysRoleVO sysRoleVO) {
        SysRoleDTO sysRoleDTO = new SysRoleDTO();
        BeanUtils.copyProperties(sysRoleVO, sysRoleDTO);
        PageUtils.startPage();
        PageDataInfo<SysRoleDTO> pageDataInfo = sysRoleService.listPage(sysRoleDTO);
        PageDataUtil<SysRoleDTO, SysRoleVO> pageDataUtil = new PageDataUtil<>();
        return pageDataUtil.transform(pageDataInfo, SysRoleVO.class);
    }

    @Log(title = "角色管理-导出", businessType = BusinessTypeEnum.EXPORT)
    @PreAuthorize("@ss.hasPermission('system:role:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysRoleVO sysRoleVO) {
        SysRoleDTO sysRoleDTO = new SysRoleDTO();
        BeanUtils.copyProperties(sysRoleVO, sysRoleDTO);
        List<SysRoleDTO> list = sysRoleService.listPage(sysRoleDTO).getData();
        ExcelUtil<SysRoleVO> util = new ExcelUtil<>(SysRoleVO.class);
        util.exportExcel(response, JsonUtils.copyList(list, SysRoleVO.class), "角色数据");
    }

    /**
     * 根据角色编号获取详细信息
     */
    @PreAuthorize("@ss.hasPermission('system:role:query')")
    @GetMapping(value = "/{roleId}")
    public Response<SysRoleVO> getInfo(@PathVariable String roleId) {
        sysRoleService.checkRoleDataScope(roleId);
        SysRoleVO sysRoleVO = new SysRoleVO();
        BeanUtils.copyProperties(sysRoleService.get(roleId), sysRoleVO);
        return Response.success(sysRoleVO);
    }


    /**
     * 查询已分配用户角色列表
     */
    @PreAuthorize("@ss.hasPermission('system:role:list')")
    @GetMapping("/authUser/allocatedList")
    public PageDataInfo<SysUserVO> allocatedList(SysUserVO sysUserVO) {
        return finalUserList(0, sysUserVO);
    }

    /**
     * 查询未分配用户角色列表
     */
    @PreAuthorize("@ss.hasPermission('system:role:list')")
    @GetMapping("/authUser/unallocatedList")
    public PageDataInfo<SysUserVO> unallocatedList(SysUserVO sysUserVO) {
        return finalUserList(1, sysUserVO);
    }

    private PageDataInfo<SysUserVO> finalUserList(Integer type, SysUserVO sysUserVO){
        SysUserDTO sysUserDTO = new SysUserDTO();
        BeanUtils.copyProperties(sysUserVO, sysUserDTO);
        PageDataInfo<SysUserDTO> pageDataInfo;
        PageUtils.startPage();
        if (type == 0) {
            pageDataInfo = sysUserService.listAllocated(sysUserDTO);
        }else{
            pageDataInfo = sysUserService.listUnallocated(sysUserDTO);
        }
        PageDataUtil<SysUserDTO, SysUserVO> pageDataUtil = new PageDataUtil<>();
        return pageDataUtil.transform(pageDataInfo, SysUserVO.class);
    }

    /**
     * 取消授权用户
     */
    @PreAuthorize("@ss.hasPermission('system:role:edit')")
    @Log(title = "角色管理-取消授权", businessType = BusinessTypeEnum.GRANT)
    @PutMapping("/authUser/cancel")
    public Response cancelAuthUser(@NotNull(message = "角色id不能为空") String roleId, @NotNull(message = "用户id不能为空") String userId) {
        sysRoleService.removeAuthUser(roleId, userId);
        return Response.success();
    }

    /**
     * 批量取消授权用户
     */
    @PreAuthorize("@ss.hasPermission('system:role:edit')")
    @Log(title = "角色管理-批量取消授权", businessType = BusinessTypeEnum.GRANT)
    @PutMapping("/authUser/cancelAll")
    public Response cancelAuthUserAll(String roleId, String[] userIds) {
        sysRoleService.removeAuthUsers(roleId, userIds);
        return Response.success();
    }

    /**
     * 批量选择用户授权
     */
    @PreAuthorize("@ss.hasPermission('system:role:edit')")
    @Log(title = "角色管理-授权", businessType = BusinessTypeEnum.GRANT)
    @PutMapping("/authUser/selectAll")
    public Response selectAuthUserAll(String roleId, String[] userIds) {
        sysRoleService.checkRoleDataScope(roleId);
        sysRoleService.saveAuthUsers(roleId, userIds);
        return Response.success();
    }

}
